/*
 * Copyright 2008 Andrej Herich
 * 
 * http://azetclient.yw.sk/
 * http://azetclient.googlecode.com/
 * 
 * This file is part of AzetClient.
 * 
 * AzetClient is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * AzetClient is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with AzetClient.  If not, see <http://www.gnu.org/licenses/>.
 */

package sk.yw.azetclient.managers;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import sk.yw.azetclient.model.Buddy;

/**
 *
 * @author error216
 */
public class BuddyListManager {
    
    private static final Logger logger =
            Logger.getLogger(BuddyListManager.class);
    
    private Map<String,Buddy> buddies = new HashMap<String,Buddy>();
    private Map<String,Buddy> others = new HashMap<String,Buddy>();
    
    private List<BuddyListManagerListener> listeners =
            new ArrayList<BuddyListManagerListener>();
    
    public BuddyListManager() {
        
    }
    
    public synchronized void addBuddyListManagerListener(BuddyListManagerListener listener) {
        listeners.add(listener);
    }
    
    public synchronized void removeBuddyListManagerListener(BuddyListManagerListener listener) {
        if (!listeners.remove(listener)) {
            logger.warn("Unable to remove MessageThreadManagerListener.");
        }
    }
    
    protected void fireBuddyAdded(Buddy buddy) {
        List<BuddyListManagerListener> listenersList =
                new ArrayList<BuddyListManagerListener>(listeners);
        BuddyListManagerEvent event = new BuddyListManagerEvent(this,
                BuddyListManagerEvent.Type.BUDDY_ADDED, buddy);
        
        for (BuddyListManagerListener listener : listenersList) {
            listener.buddyAdded(event);
        }
    }
    
    protected void fireBuddyChanged(Buddy buddy) {
        List<BuddyListManagerListener> listenersList =
                new ArrayList<BuddyListManagerListener>(listeners);
        BuddyListManagerEvent event = new BuddyListManagerEvent(this,
                BuddyListManagerEvent.Type.BUDDY_CHANGED, buddy);
        
        for (BuddyListManagerListener listener : listenersList) {
            listener.buddyChanged(event);
        }
    }
    
    protected void fireBuddyRemoved(Buddy buddy) {
        List<BuddyListManagerListener> listenersList =
                new ArrayList<BuddyListManagerListener>(listeners);
        BuddyListManagerEvent event = new BuddyListManagerEvent(this,
                BuddyListManagerEvent.Type.BUDDY_REMOVED, buddy);
        
        for (BuddyListManagerListener listener : listenersList) {
            listener.buddyRemoved(event);
        }
    }
    
    protected void fireOtherAdded(Buddy buddy) {
        List<BuddyListManagerListener> listenersList =
                new ArrayList<BuddyListManagerListener>(listeners);
        BuddyListManagerEvent event = new BuddyListManagerEvent(this,
                BuddyListManagerEvent.Type.OTHER_ADDED, buddy);
        
        for (BuddyListManagerListener listener : listenersList) {
            listener.otherAdded(event);
        }
    }
    
    protected void fireOtherChanged(Buddy buddy) {
        List<BuddyListManagerListener> listenersList =
                new ArrayList<BuddyListManagerListener>(listeners);
        BuddyListManagerEvent event = new BuddyListManagerEvent(this,
                BuddyListManagerEvent.Type.OTHER_CHANGED, buddy);
        
        for (BuddyListManagerListener listener : listenersList) {
            listener.otherChanged(event);
        }
    }
    
    protected void fireOtherRemoved(Buddy buddy) {
        List<BuddyListManagerListener> listenersList =
                new ArrayList<BuddyListManagerListener>(listeners);
        BuddyListManagerEvent event = new BuddyListManagerEvent(this,
                BuddyListManagerEvent.Type.OTHER_REMOVED, buddy);
        
        for (BuddyListManagerListener listener : listenersList) {
            listener.otherRemoved(event);
        }
    }
    
    public synchronized Collection<Buddy> getBuddies() {
        return Collections.unmodifiableCollection(buddies.values());
    }
    
    public synchronized Buddy getBuddy(String name) {
        if (name == null)
            throw new IllegalArgumentException("Null pointer in name.");
        
        Buddy buddy = buddies.get(name.toLowerCase(Locale.ENGLISH));
        if (buddy == null) {
            buddy = new Buddy();
            buddy.setName(name.toLowerCase(Locale.ENGLISH));
            logger.warn("Unknown buddy: " + name);
        }
        return buddy;
    }
    
    public synchronized void setBuddies(Collection<Buddy> newBuddies) {
        Set<Buddy> oldBuddies = new HashSet(this.buddies.values());
        for (Buddy buddy : oldBuddies) {
            if (!newBuddies.contains(buddy)) {
                removeBuddy(buddy.getName());
            }
        }
        for (Buddy buddy : newBuddies) {
            addBuddy(buddy);
        }
    }
    
    public synchronized void addBuddy(Buddy newBuddy) {
        if (newBuddy == null)
            throw new IllegalArgumentException("Null pointer in newBuddy");
        
        Buddy oldBuddy = buddies.get(
                newBuddy.getName().toLowerCase(Locale.ENGLISH));
        
        if (oldBuddy == null) {
            buddies.put(newBuddy.getName().toLowerCase(Locale.ENGLISH),
                    newBuddy);
            oldBuddy = newBuddy;
        
            fireBuddyAdded(oldBuddy);
        } else {
            updateBuddy(oldBuddy, newBuddy);
            
            fireBuddyChanged(oldBuddy);
        }
    }
    
    public synchronized void removeBuddy(String name) {
        if (name == null)
            throw new IllegalArgumentException("Null pointer in name.");
        
        fireBuddyRemoved(buddies.remove(name));
    }
    
    public synchronized Collection<Buddy> getOthers() {
        return Collections.unmodifiableCollection(others.values());
    }
    
    public synchronized Buddy getOther(String name) {
        if (name == null)
            throw new IllegalArgumentException("Null pointer in name.");
        
        return others.get(name.toLowerCase(Locale.ENGLISH));
    }
    
    public synchronized void addOther(Buddy newBuddy) {
        if (newBuddy == null)
            throw new IllegalArgumentException("Null pointer in newBuddy");
        
        Buddy oldBuddy = others.get(
                newBuddy.getName().toLowerCase(Locale.ENGLISH));
        
        if (oldBuddy == null) {
            others.put(newBuddy.getName().toLowerCase(Locale.ENGLISH),
                    newBuddy);
            oldBuddy = newBuddy;
        
            fireOtherAdded(oldBuddy);
        } else {
            updateBuddy(oldBuddy, newBuddy);
            
            fireOtherChanged(oldBuddy);
        }
    }
    
    public synchronized void removeOther(String name) {
        if (name == null)
            throw new IllegalArgumentException("Null pointer in name.");
        
        fireOtherRemoved(others.remove(name));
    }
    
    protected Buddy updateBuddy(Buddy oldBuddy, Buddy newBuddy) {
        int integer;
        String string;
        Buddy.Gender gender;
        Date date;
        Buddy.Status status;

        integer = newBuddy.getId();
        if (integer != 0) {
            oldBuddy.setId(integer);
        }

        string = newBuddy.getAlias();
        if (string != null) {
            oldBuddy.setAlias(string);
        }

        gender = newBuddy.getGender();
        if (gender != null) {
            oldBuddy.setGender(gender);
        }

        integer = newBuddy.getAge();
        if (integer != -1) {
            oldBuddy.setAge(integer);
        }

        string = newBuddy.getLocation();
        if (string != null) {
            oldBuddy.setLocation(string);
        }

        date = newBuddy.getLastLogin();
        if (date != null) {
            oldBuddy.setLastLogin(date);
        }

        status = newBuddy.getStatus();
        if (status != null) {
            oldBuddy.setStatus(status);
        }

        string = newBuddy.getRoom();
        if (string != null) {
            oldBuddy.setRoom(string);
        }

        integer = newBuddy.getRoomNo();
        if (integer != 0) {
            oldBuddy.setRoomNo(integer);
        }
        
        return oldBuddy;
    }

}
